package it.cums.core.util;

import it.cums.core.Activator;
import it.cums.core.model.Customer;
import it.cums.core.model.Order;
import it.cums.core.model.Orders;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class OrderManager {
	private static OrderManager orderManager;
	
	private OrderManager() {
	}
	
	public static OrderManager getInstance() {
		if (orderManager == null) {
			orderManager = new OrderManager();
		}
		return orderManager;
	}
	
	public void createAndStoreOrder(Orders orders, String status, Customer c, String priority, Date orderDate, Date deliveryDate, double totalPrice, int discount, double endPrice) throws Exception {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			Order o = new Order();
			o.setStatus(status);
			o.setCustomer(c);
			o.setPriority(priority);
			o.setOrderDate(orderDate);
			o.setDeliveryDate(deliveryDate);
			o.setTotalPrice(totalPrice);
			o.setDiscount(discount);
			o.setEndPrice(endPrice);
			session.save(o);
			tx.commit();
			orders.addOrder(o);
		} catch (Exception e) {
			Activator.getDefault().logError(e.getMessage(), e);
			MessageCreator.showErrorMessage("Order can't be added to the database!");
			HibernateUtil.rollback(tx);
			throw e;
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
	
	public void updateOrder(Order order, String status, Customer c, String priority, Date orderDate, Date deliveryDate, double totalPrice, int discount, double endPrice) {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			order.setStatus(status);
			order.setCustomer(c);
			order.setPriority(priority);
			order.setOrderDate(orderDate);
			order.setDeliveryDate(deliveryDate);
			order.setTotalPrice(totalPrice);
			order.setDiscount(discount);
			order.setEndPrice(endPrice);
			InvoiceManager.getInstance().storeInvoices(session, order.getInvoices(), order);
			OrderedProductManager.getInstance().storeOrderedProducts(session, order.getOrderedProducts(), order);
			session.update(order);
			tx.commit();
		} catch (Exception e) {
			Activator.getDefault().logError(e.getMessage(), e);
			MessageCreator.showErrorMessage("Order can't be updated in the database!");
			HibernateUtil.rollback(tx);
		} finally {
			HibernateUtil.closeSession(session);
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Order> listOrders(Customer c) {
		Session session = null;
		Transaction tx = null;
		List<Order> orders = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
		    tx = session.beginTransaction();
		    Query query = session.createQuery("from Order as o where o.customer.id = :id order by o.id");
		    query.setInteger("id", c.getId());
		    orders = query.list();
		    tx.commit();
		} catch (Exception e) {
			Activator.getDefault().logError(e.getMessage(), e);
			HibernateUtil.rollback(tx);
		} finally {
			HibernateUtil.closeSession(session);
		}
		return orders;
    }
	
	public boolean deleteOrder(Orders orders, Order order) {
		boolean successful = false;
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			tx = session.beginTransaction();
			OrderedProductManager.getInstance().deleteOrderedProducts(session, order);
			InvoiceManager.getInstance().deleteInvoices(session, order);
			session.delete(order);
			tx.commit();
			orders.removeOrder(order);
			successful = true;
		} catch (Exception e) {
			Activator.getDefault().logError(e.getMessage(), e);
			MessageCreator.showErrorMessage("Order 'Order " + order.getId() + "' can't be removed from the database!");
			HibernateUtil.rollback(tx);
		} finally {
			HibernateUtil.closeSession(session);
		}
		return successful;
	}
	
	public void deleteOrders(Session session, Customer customer) throws Exception {
		for (Order order : customer.getOrders().getOrders()) {
			InvoiceManager.getInstance().deleteInvoices(session, order);
			OrderedProductManager.getInstance().deleteOrderedProducts(session, order);
			Query query = session.createQuery("delete Order o where o.id = :id");
			query.setInteger("id", order.getId());
			query.executeUpdate();
		}
	}
}